#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @FileName  :chapter03.py
# @Time      :2021/03/25 14:25:30
# @Author    :Raink


from typing import Optional
from fastapi import APIRouter
from pydantic.fields import Field

app03 = APIRouter()
"""路径参数"""
"""
路由顺序按照从上到下，例如这里，如果参数就是parameters,
那么实际上是按照最前面的来匹配
"""
@app03.get("/path/parameters")
def path_params01():
    return {"message", "This is a message"}

@app03.get("/path/{parameters}")
def path_params01(parameters: str):
    return {"message": parameters}

"""
路径参数中可以使用枚举类型
"""
from enum import Enum


class CityName(str, Enum):
    BeiJing = "BeiJing China"
    ShangHai = "Shanghai China"

@app03.get("/enum/{city}")
async def latest(city: CityName):
    if city == CityName.BeiJing:
        return {"city_name": city, "confired": 1492, "depth": 8}
    if city == CityName.ShangHai:
        return {"city_name": city, "confired": 971, "depth": 9}
    return {"city_name": city, "latest": "unkonw"}

"""
路径参数传递文件路径（文件路径中有很多斜杠）
需要在路径参数中做表示  /{xxx:path}
"""
@app03.get("/files/{file_path:path}")
def filepath(file_path: str):
    return f"The file path is {file_path}"

"""
路径参数中的数值和正则表达式
需要从fastapi中导入Path模块来对路径参数做校验
"""
from fastapi import Path

@app03.get("/path/{num}")
def path_params_validate(
    num: int = Path(..., title="Your Number", description="The description of the num", ge=1, le=10)
):
    return num

"""
查询参数和字符串验证
"""
# from typing import Optional
@app03.get("/query")  #给了默认值就是选填参数
def page_limit(page: int = 1, limit:Optional[int]=None):
    if limit:
        return {"page": page, "limit": limit}
    return {"page": page}

"""
些时候，传递过来的值，可以直接转换成bool
数字0、1 以及yes、 no、on等
"""
@app03.get("/query/bool/conversion")
def type_conversion(param: bool = False):
    return param

"""
字符串的验证，比如限制长度，或者用正则表达式去匹配
需要从fastapi中引入Query
alias:别名
"""
from fastapi import Query
from typing import List

@app03.get("/query/validations")
def query_params_validate(
    value: str = Query(..., min_length=8, max_length=16, regex="^a"),
    values: List[str] = Query(default=["V1", "V2"], alias="alias_name")
):
    return value, values

"""
请求体与字段
"""
from pydantic import BaseModel

class Cityinfo(BaseModel):
    name: str = Field(..., example="Beijing")
    country: str
    country_code: str = None
    country_population: int = Field(default=800, title="人口数量", description="国家的人口", ge=800)
    class Config:
        # 必须是schema_extra，其他名字的就不会被识别
        schema_extra = {
            "example":{   #example只是注解，值不会被验证
                "name":"Shanghai",
                "country":"china",
                "country_code": "CN",
                "country_population": "1400000000"
            }
        }

@app03.post("/request_body/city")
def city_info(city: Cityinfo):
    print(city.name, city.country)
    return city.dict()

"""
多参数混合
"""
@app03.put("/request_body/city/{name}")
def mix_city_info(
    name: str,
    city01: Cityinfo,
    city02: Cityinfo,
    confirmed: int = Query(ge=0, description="确诊数", default=0), 
    death: int = Query(ge=0, description="死亡数", default=0)
):
    if name == "Shanghai":
        return {"Shanghai": {"confirmed": confirmed, "death": death}}
    return city01.dict(), city02.dict()

"""
数据格式嵌套请求体
"""
"""
请求体数据字段校验->Field
路径参数校验->Path
查询参数校验->Query
"""
from datetime import date

class Data(BaseModel):
    city: List[Cityinfo] = None
    date: date
    confirmed: int = Field(ge=0, description="确诊数", default=0)
    death: int = Field(ge=0, description="死亡数", default=0)
    recovered: int = Field(ge=0, description="死亡数", default=0)

@app03.put("/request_body/nested")
def nested_models(data: Data):
    return data

"""Cookie和header"""
"""
Cookie是在Header中的，在header中，参数名必须是“Cookie”，
参数以cookie_id=xxx的形式
"""
from fastapi import Cookie, Header

@app03.get("/cookie")
def cookie(cookie_id: Optional[str]=Cookie(None)):
    return {"cookie_id": cookie_id}

@app03.get("/header")
def header(
    user_agent: Optional[str]=Header(None, convert_underscores=True),
    x_token: List[str]=Header(None)
):
    return {
        "User-Agent": user_agent,
        "x_token": x_token
    }